/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.spi.jsonser.base;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final
class StringUtils {
    public static final String CarriageReturnLineFeed = "\r\n";
    public static final String Empty = "";
    public static final char CarriageReturn = '\r';
    public static final char LineFeed = '\n';
    public static final char Tab = '\t';


    public static boolean isNullOrEmpty(String value) {
        return value == null || "".equals(value);
    }
    /**
     * Determines whether the string is all white space. Empty string will return <c>false</c>.
     *
     * @param s The string to test whether it is all white space.
     * @return <c>true</c> if the string is all white space; otherwise, <c>false</c>.
     */
    public static boolean isWhiteSpace(String s) {
        if (s == null) {
            throw new IllegalArgumentException(s);
        }

        if (s.length() == 0) {
            return false;
        }

        for (int i = 0; i < s.length(); i++) {
            if (!Character.isWhitespace(s.charAt(i))) {
                return false;
            }
        }

        return true;
    }

    public static boolean isEmpty(final CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    public static String toCamelCase(String s) {
        if (s == null || s.equals("") || !Character.isUpperCase(s.charAt(0))) {
            return s;
        }
        char[] chars = s.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            if (i == 1 && !Character.isUpperCase(chars[i])) {
                break;
            }

            boolean hasNext = (i + 1 < chars.length);
            if (i > 0 && hasNext && !Character.isUpperCase(chars[i + 1])) {
                // if the next character is a space, which is not considered uppercase
                // (otherwise we wouldn't be here...)
                // we want to ensure that the following:
                // 'FOO bar' is rewritten as 'foo bar', and not as 'foO bar'
                // The code was written in such a way that the first word in uppercase
                // ends when if finds an uppercase letter followed by a lowercase letter.
                // now a ' ' (space, (char)32) is considered not upper
                // but in that case we still want our current character to become lowercase
                //Java版临时屏蔽
                if (CheckSeparator(chars[i + 1])) {
                    chars[i] = toLower(chars[i]);
                }

                break;
            }
            chars[i] = toLower(chars[i]);
        }

        return new String(chars);
    }

    private static boolean CheckSeparator(char cha) {
        char[] separator = new char[21];
        separator[0] = '\u0020';
        separator[1] = '\u00a0';
        separator[2] = '\u2028';
        separator[3] = '\u2029';
        separator[4] = '\u1680';
        separator[5] = '\u2000';
        separator[6] = '\u2001';
        separator[7] = '\u2002';
        separator[8] = '\u2003';
        separator[9] = '\u2004';
        separator[10] = '\u2005';
        separator[11] = '\u2006';
        separator[12] = '\u2007';
        separator[13] = '\u2008';
        separator[14] = '\u2009';
        separator[15] = '\u200A';
        separator[16] = '\u200B';
        separator[17] = '\u2028';
        separator[18] = '\u2029';
        separator[19] = '\u202F';
        separator[20] = '\u3000';
        for (char item : separator) {
            if (item == cha) {
                return true;
            }
        }
        return false;
    }

    private static char toLower(char c) {
        c = Character.toLowerCase(c);
        return c;
    }

    public enum SnakeCaseState {
        Start,
        Lower,
        Upper,
        NewWord;

        public
        int getValue() {
            return this.ordinal();
        }

        public static
        SnakeCaseState forValue(int value) {
            return values()[value];
        }
    }

    public static String toSnakeCase(String s) {
        if (s == null || s == "") {
            return s;
        }

        StringBuilder sb = new StringBuilder();
        SnakeCaseState state = SnakeCaseState.Start;

        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ' ') {
                if (state != SnakeCaseState.Start) {
                    state = SnakeCaseState.NewWord;
                }
            } else if (Character.isUpperCase(s.charAt(i))) {
                switch (state) {
                    case Upper:
                        boolean hasNext = (i + 1 < s.length());
                        if (i > 0 && hasNext) {
                            char nextChar = s.charAt(i + 1);
                            if (!Character.isUpperCase(nextChar) && nextChar != '_') {
                                sb.append('_');
                            }
                        }
                        break;
                    case Lower:
                    case NewWord:
                        sb.append('_');
                        break;
                }

                char c;

                c = Character.toLowerCase(s.charAt(i));

                sb.append(c);

                state = SnakeCaseState.Upper;
            } else if (s.charAt(i) == '_') {
                sb.append('_');
                state = SnakeCaseState.Start;
            } else {
                if (state == SnakeCaseState.NewWord) {
                    sb.append('_');
                }

                sb.append(s.charAt(i));
                state = SnakeCaseState.Lower;
            }
        }

        return sb.toString();
    }

    public static boolean isHighSurrogate(char c) {
        return (c >= 55296 && c <= 56319);
    }

    public static boolean isLowSurrogate(char c) {

        return (c >= 56320 && c <= 57343);

    }


    public static boolean startsWith(String source, char value) {
        return (source.length() > 0 && source.charAt(0) == value);
    }


    public static boolean endsWith(String source, char value) {
        return (source.length() > 0 && source.charAt(source.length() - 1) == value);
    }


    public static String trim(String s, int start, int length) {
        if (s == null) {
            throw new UnsupportedOperationException();
        }
        if (start < 0) {
            throw new UnsupportedOperationException("start");
        }
        if (length < 0) {
            throw new UnsupportedOperationException("length");
        }
        int end = start + length - 1;
        if (end >= s.length()) {
            throw new UnsupportedOperationException("length");
        }
        for (; start < end; start++) {
            if (!Character.isWhitespace(s.charAt(start))) {
                break;
            }
        }
        for (; end >= start; end--) {
            if (!Character.isWhitespace(s.charAt(end))) {
                break;
            }
        }
        return s.substring(start, end + 1);
    }

    public static boolean containSpecialChar(String str) {
        String regEx =  ".*[`~!%*+={}':;',\\[\\].<>/?~+{}\\\\]+.*";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.matches();
    }

    public static boolean isNullOrEmpty(Object value)
    {
        if(value==null)
            return true;
        if(value instanceof String)
            return value.toString().equals("");
        return false;
    }
}
